package ae.pcfc.cldos.online.web.controller.client.company.visitvisa;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.soap.client.SoapFaultClientException;

import ae.pcfc.cldos.online.common.ConstantsCommon.Steps;
import ae.pcfc.cldos.online.common.delegate.FnpGSDelegate;
import ae.pcfc.cldos.online.common.delegate.VisitVisaDelegate;
import ae.pcfc.cldos.online.common.exception.GSAppException;
import ae.pcfc.cldos.online.common.exception.LeaseExpireException;
import ae.pcfc.cldos.online.common.exception.LicenseErrorRemarkException;
import ae.pcfc.cldos.online.common.exception.LicenseExpiredException;
import ae.pcfc.cldos.online.common.exception.PaymentException;
import ae.pcfc.cldos.online.common.exception.RequestAllreadyExistException;
import ae.pcfc.cldos.online.common.exception.UltimusAppException;
import ae.pcfc.cldos.online.common.exception.UpdateClientDtlException;
import ae.pcfc.cldos.online.common.exception.VisitorAllreadyExistException;
import ae.pcfc.cldos.online.common.vo.AppSaveResponseVO;
import ae.pcfc.cldos.online.common.vo.CommentsVO;
import ae.pcfc.cldos.online.common.vo.FileVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.VisitVisaMainVO;
import ae.pcfc.cldos.online.common.vo.employee.details.AddressDetailsVO;
import ae.pcfc.cldos.online.common.vo.employee.details.EmployeeDetailsVO;
import ae.pcfc.cldos.online.common.vo.employee.details.PassportDetailsVO;
import ae.pcfc.cldos.online.common.vo.employee.details.PersonalDetailsVO;
import ae.pcfc.cldos.online.common.vo.employee.details.VisitVisaVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPCatalogVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPParameterVO;
import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.web.Constants;
import ae.pcfc.cldos.online.web.PageType;
import ae.pcfc.cldos.online.web.ViewPath;
import ae.pcfc.cldos.online.web.ViewUtils;
import ae.pcfc.cldos.online.web.controller.base.BaseNewVisaController;
import ae.pcfc.cldos.online.web.exception.ResourceNotFoundException;
import ae.pcfc.cldos.online.web.model.FilesIncomingBean;
import ae.pcfc.cldos.online.web.model.VisitVisaLicenseInfo;
import ae.pcfc.cldos.online.web.services.breadcrumbs.BreadCrumbsFactoryService;
import ae.pcfc.cldos.online.web.services.fnp.FnpParametersCheckService;

/**
 * 
 * @author Asna
 * 
 */
@Controller
@RequestMapping(value = ViewPath.__COMPANY_VISIT_VISA_REGISTRATION)
public class CompanyVisitVisaRegistrationController extends BaseNewVisaController {

	private FnpGSDelegate FnpGSDelegate;
	Integer visitVisaMonth = 1;

	@Resource(name = "FnpGSDelegate")
	public void setFnpGSDelegate(FnpGSDelegate FnpGSDelegate) {
		this.FnpGSDelegate = FnpGSDelegate;
	}

	@Autowired
	@Qualifier("visitVisaDelegate")
	private VisitVisaDelegate visitVisaDelegate;

	@Autowired
	private FnpParametersCheckService fnpParametersCheckService;
	
	private static final String VISIT_VISA_VIEW_PATH = "client.company.visitvisa.form";

	// Added by Asna for including the FNP Details
	/**
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@ModelAttribute(Constants.__FNP_CATALOG_MODEL_KEY)
	public List<FNPCatalogVO> populateFinanceReviewerInfoModel(
			HttpServletRequest request,ModelMap model, @RequestParam(Constants.__EMP_SOURCE_PARAM) String empSourceParam) {
		if (securityService.isCompanyAdmin()) {
			String serviceCode = Constants.__VISIT_VISA_ONE_MONTH_SERVICE_CODE;
			if(empSourceParam.equals("3")){
				serviceCode = Constants.__VISIT_VISA_THREE_MONTH_SERVICE_CODE;
			}
			model.put("bgRequired", ConstantsGS.__BG_VISIT_VISA);
			return FnpGSDelegate.getFnpCatalogVOsByServiceCode(serviceCode);
		} else {
			return Collections.EMPTY_LIST;
		}
	}

	/**
	 * @param appId
	 * @param model
	 * @param visitVisaLicenseInfo
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(method=RequestMethod.GET, value="/resubmitForm.htm")
	public ModelAndView resubmitForm(
			@RequestParam String appId,
			ModelMap model,
			@ModelAttribute(value = Constants.__COMPANY_VISIT_VISA_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) VisitVisaLicenseInfo visitVisaLicenseInfo) throws Exception{
		
		populateResubmitInfo(appId, visitVisaLicenseInfo, model);
		breadCrumbsFactoryService.populateMainAdminRewiewBreadcrumb(model, appId, BreadCrumbsFactoryService.TASK_TYPE_RESUBMIT);
		return new ModelAndView(VISIT_VISA_VIEW_PATH);
	}
	
	/**
	 * @param appId
	 * @param visitVisaInfo
	 * @param model
	 * @throws NumberFormatException
	 * @throws Exception
	 */
	private void populateResubmitInfo(String appId, VisitVisaLicenseInfo visitVisaInfo, ModelMap model) throws NumberFormatException, Exception{
		
		VisitVisaMainVO visitVisaMainVO = visitVisaDelegate.getVisitVisaDetailByAppId(
				encryptionDelegate.decodeAndDecrypt(appId), getUserVO(), Steps.RESUBMIT);
		List<FileVO> fileVOList = visitVisaMainVO.getFileVOList();
		model.put("files", fileVOList);
		model.put("isResubmit", true);
		model.put("appId", appId);
		model.put("comments", visitVisaMainVO.getApplicationCommentVOs());
		model.put("submitUri", ViewPath.__COMPANY_VISIT_VISA_REGISTRATION+"/resubmitForm.htm?appId="+appId);
		if(visitVisaInfo!=null){
			AddressDetailsVO addressDetailsVO = visitVisaMainVO.getAddressDetailsVO();
			mapper.map(addressDetailsVO, visitVisaInfo);
			EmployeeDetailsVO employeeDetailsVO = visitVisaMainVO.getEmployeeDetailsVO();
			mapper.map(employeeDetailsVO, visitVisaInfo);
			PassportDetailsVO passportDetailsVO = visitVisaMainVO.getPassportDetailsVO();
			mapper.map(passportDetailsVO, visitVisaInfo);
			PersonalDetailsVO personalDetailsVO = visitVisaMainVO.getPersonalDetailsVO();
			mapper.map(personalDetailsVO, visitVisaInfo);
			VisitVisaVO visitVisaVO = visitVisaMainVO.getVisitVisaVO();
			mapper.map(visitVisaVO, visitVisaInfo);
			CommentsVO commentsVO = visitVisaMainVO.getCommentsVO();
			mapper.map(commentsVO, visitVisaInfo);
			visitVisaMonth = new Integer(visitVisaVO.getVvMonth());
		}
		
	}
	
	/**
	 * @param appId
	 * @param model
	 * @throws NumberFormatException
	 * @throws Exception
	 */
	private void populateResubmitInfo(String appId, ModelMap model) throws NumberFormatException, Exception{
		populateResubmitInfo(appId, null, model);
	}
	
	/**
	 * @param request
	 * @param model
	 * @param visitVisaLicenseInfo
	 * @return
	 */
	@RequestMapping(value = "/form.htm", method = RequestMethod.GET)
	public ModelAndView login(
			HttpServletRequest request,
			ModelMap model,
			@ModelAttribute(value = Constants.__COMPANY_VISIT_VISA_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) VisitVisaLicenseInfo visitVisaLicenseInfo) {

		model.put("submitUri", ViewPath.__COMPANY_VISIT_VISA_REGISTRATION+"/form.htm");
		model.put("isResubmit", false);
		String empSourceParam = request
				.getParameter(Constants.__EMP_SOURCE_PARAM);

		Integer empSource = null;

		try {
			empSource = Integer.parseInt(empSourceParam);
		} catch (NumberFormatException e) {
		}

		if (empSource == null  || empSource < 0) {
			throw new ResourceNotFoundException();
		} else {
			visitVisaLicenseInfo.setStrMonth(empSource);
			visitVisaMonth=empSource;
		}
		breadCrumbsFactoryService.populateVisitVisaBreadCrumb(model, empSource);
		return new ModelAndView(VISIT_VISA_VIEW_PATH);
	
	}


	/**
	 * @param model
	 * @param request
	 * @param filesIncomingBean
	 * @param fileErrors
	 * @param employmentVisaLicenseInfo
	 * @param errors
	 * @return
	 * @throws Throwable
	 */
	@RequestMapping(method = RequestMethod.POST, value={"/form.htm", "/resubmitForm.htm"})
	public ModelAndView form(
			ModelMap model,
			HttpServletRequest request,
			@RequestParam(required=false, defaultValue="false") boolean isResubmit,
			@RequestParam(required=false) String appId,
			@RequestParam(required = false) String fnpServiceCode,
			@ModelAttribute @Valid FilesIncomingBean filesIncomingBean,
			BindingResult fileErrors,
			@ModelAttribute(value = Constants.__COMPANY_VISIT_VISA_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) @Valid VisitVisaLicenseInfo visitVisaLicenseInfo,
			BindingResult errors) throws Throwable {

			ModelAndView mav = null;
			boolean isSubmit = WebUtils.hasSubmitParameter(request, Constants.SUBMIT_BUTTON);
			System.out.println("isSubmit : " + isSubmit);
			List<FNPParameterVO> allParams = null;		

			if (securityService.isCompanyAdmin()
					&& (fnpServiceCode == null || fnpServiceCode.isEmpty())) {
				errors.reject("no.payment.code");
			} else if (securityService.isCompanyAdmin()) {
				allParams = FnpGSDelegate.retreiveAllFNPParameters(
						Arrays.asList(new String[] { fnpServiceCode }));
				List<FNPParameterVO> notFilled = fnpParametersCheckService
						.feelParamsAndGetNotFeeled(request, allParams);
				if (notFilled.size() > 0) {
					errors.reject("fgfg", "Recomplete payment info please");
				}
			}
			if (errors.hasErrors() || fileErrors.hasErrors()) {
				
				System.out.println("there is errors : " );
				for(ObjectError error : errors.getAllErrors())
				{
					System.out.println(error.getCode() + " " + error.getDefaultMessage());
				}
				/*Integer empSource = visitVisaLicenseInfo.getEmployeeSource();
				if(empSource==null || empSource>3 || empSource<0){
					throw new ResourceNotFoundException();
				} else {
					breadCrumbsFactoryService.populateEmploymentVisaBreadCrumb(model, empSource);
				}*/
				mav =  new ModelAndView(VISIT_VISA_VIEW_PATH);;

			}else{
				visitVisaLicenseInfo.setStrMonth(visitVisaMonth);
				EmployeeDetailsVO employeeDetailsVO = new EmployeeDetailsVO();
				mapper.map(visitVisaLicenseInfo, employeeDetailsVO);
				PassportDetailsVO passportDetailsVO = new PassportDetailsVO();
				mapper.map(visitVisaLicenseInfo, passportDetailsVO);
				PersonalDetailsVO personalDetailsVO = new PersonalDetailsVO();
				mapper.map(visitVisaLicenseInfo, personalDetailsVO);
				AddressDetailsVO addressDetailsVO = new AddressDetailsVO();
				mapper.map(visitVisaLicenseInfo, addressDetailsVO);
				CommentsVO commentsVO = new CommentsVO();
				mapper.map(visitVisaLicenseInfo, commentsVO);
				VisitVisaVO visitVisaVO = new VisitVisaVO();
				mapper.map(visitVisaLicenseInfo, visitVisaVO);
				if(visitVisaMonth==1){
					visitVisaVO.setServiceCode(Constants.__VISIT_VISA_ONE_MONTH_SERVICE_CODE);
				}else{
					visitVisaVO.setServiceCode(Constants.__VISIT_VISA_THREE_MONTH_SERVICE_CODE);
				}

				UserVO userVO = new UserVO();
				userVO.setUsername(securityService.getLoginedUsername());
				userVO.setEmployee(securityService.isCompanyEmployee());
				userVO.setAdmin(securityService.isCompanyAdmin());

				VisitVisaMainVO visaMainVO = new VisitVisaMainVO();
				visaMainVO.setAddressDetailsVO(addressDetailsVO);
				visaMainVO.setEmployeeDetailsVO(employeeDetailsVO);
				visaMainVO.setPassportDetailsVO(passportDetailsVO);
				visaMainVO.setPersonalDetailsVO(personalDetailsVO);
				visaMainVO.setCommentsVO(commentsVO);
				visaMainVO.setFileVOList(getFileVOList(filesIncomingBean));
				visaMainVO.setVisitVisaVO(visitVisaVO);
				visaMainVO.setUserVO(userVO);

				visaMainVO.setFnpServiceCode(fnpServiceCode);
				visaMainVO.setFnpParams(allParams);


				String refNo = null;
				String incidentNo = null;
				try{
					AppSaveResponseVO appSaveResponseVO=null;
					if(isResubmit){
						 appSaveResponseVO = visitVisaDelegate.reSubmit(visaMainVO,encryptionDelegate.decodeAndDecrypt(appId));
					}else{
						 appSaveResponseVO = visitVisaDelegate.submit(visaMainVO);
					}
					refNo = appSaveResponseVO.getReferenceNo();
					incidentNo = appSaveResponseVO.getIncidentNo();
					
				}catch (PaymentException e) {
					errors.reject("error.payment");
				}catch (LicenseErrorRemarkException e) {
					errors.reject("license.errorremark");
				}catch (LicenseExpiredException e) {
					errors.reject("license.expire");
				}catch (RequestAllreadyExistException e) {
					errors.reject("visitrequest.exist");
				}catch (VisitorAllreadyExistException e) {
					errors.reject("visitor.exist");
				}catch(UpdateClientDtlException e){
					errors.reject("update.client.dtls");
				}catch(GSAppException e){
					errors.reject("unable.to.proceed.gs.down");
				}catch(UltimusAppException e){
					errors.reject("unable.to.proceed.ultimus.down");
				}catch(WebServiceIOException e){
					e.printStackTrace();
					errors.reject("unable.to.proceed.gs.fnp.down");
				}catch(SoapFaultClientException e){
					e.printStackTrace();
					errors.reject("unable.to.proceed.gs.fnp.down");
				}catch(Exception e){
					e.printStackTrace();
					errors.reject("unable.to.proceed");
				}

				Map<String, String> paramMap = new HashMap<String, String>();
				paramMap.put(Constants.__REFRENCE_NO, refNo);
				if(incidentNo != null){
					paramMap.put(Constants.__INCIDENT_NO, incidentNo);
				}
				
				if(errors.hasErrors()){
					mav =  new ModelAndView(VISIT_VISA_VIEW_PATH);
				}else{
					mav = new ModelAndView(ViewUtils.getRedirect(ViewPath.__CONFIRMATION, PageType.SHOW, paramMap));
				}

			}

			if((errors.hasErrors() || fileErrors.hasErrors()) ){
				if(isResubmit){
					populateResubmitInfo(appId, model);
				} else{
					model.put("submitUri", ViewPath.__COMPANY_VISIT_VISA_REGISTRATION+"/form.htm");
				}
			}
			return mav;

	}

}
